package custom.cards;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import custom.cards.GameRequest.RequestType;

import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.graphics.Paint.Align;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.Layout.Alignment;
import android.util.Log;
import android.view.Display;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.RelativeLayout.*;
import android.view.ViewGroup;

public class GamePlayActivity extends Activity {

	public static String gameToJoin;
	public static String gameID;
	public static String playerID;
	public static Activity parent;
	private RelativeLayout theLayout;
	// RelativeLayout thisLayout;
	private int screenHeight, screenWidth, x;
	public static HashMap<String, Player> currPlayers = new HashMap<String, Player>();
	public static ArrayList<Card> playerCards = new ArrayList<Card>();
	private CommunityPlayer theCommunity;
	public static boolean addListeners = true;
	public static Handler mHandler;
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_gameplay);
		parent = this;
		currPlayers.clear();
		
		 mHandler = new Handler(Looper.getMainLooper()) 
		 {
		 
			  /*
		         * handleMessage() defines the operations to perform when
		         * the Handler receives a new Message to process.
		         */
		        @Override
		        public void handleMessage(Message inputMessage) 
		        {
		            Intent i = (Intent) inputMessage.obj;
		            Log.d("handleMessage GamePlay", "Fired: " + i.toString());
		           if( i != null)
		           {
		        	   try
		        	   {
		        		   ProcessIntent(i); 
		        	   }
		        	   catch(Exception ex)
		        	   {

		        		   Log.e("Exception in GamePlay:", "Exception", ex);
		        	   } 
		        	  
		           }
		           
		        }
			 
		 };
		

		

		UpdateScreenSize();		

		theLayout = (RelativeLayout) findViewById(R.id.RelativeLayout);
		


		if(gameToJoin != null)
		{
			try 
			{

				
				
				GameRequest joinGame = new GameRequest(gameToJoin.toString(),GamePlayActivity.playerID,MainActivity.playerName,RequestType.JoinGame);
				new NetworkTask(joinGame).execute();
				
				this.setTitle("Waiting for Server Response...");
			}
			catch(Exception e)
			{
				Toast.makeText(this, "Invalid GameID", Toast.LENGTH_LONG).show();
				finish();
			}
		}
		
			 
		 

		 final ImageView boxes = new ImageView(this);
		 boxes.setImageDrawable(this.getResources().getDrawable(R.drawable.g_outline5));
		 LayoutParams newParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		 boxes.setLayoutParams(newParams);
		 
		 final ViewTreeObserver vto = boxes.getViewTreeObserver();
		 vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
		     public boolean onPreDraw() 
		     {
		    	 int numOfWidth = screenWidth/boxes.getMeasuredWidth();
		 		int numOfHeight = screenHeight/boxes.getMeasuredHeight();
		 		
		 		int spaceWidth = screenWidth/numOfWidth;
		 		int spaceHeight = screenHeight/numOfHeight;
		 		
		    	 for(int i = 0; i < numOfWidth;i++)
		 		{
		 			for(int j = 0; j < numOfHeight;j++)
		 			{
		 				 ImageView box = new ImageView(GamePlayActivity.parent);
		 				 box.setImageDrawable(GamePlayActivity.parent.getResources().getDrawable(R.drawable.g_outline5));
		 				 LayoutParams newParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		 				
		 				box.setId(i+j);
		 				
		 				if(i > 0)
	 					{
	 						newParams.addRule(RelativeLayout.RIGHT_OF, i-1);
	 					}
	 					else
	 					{
	 						newParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
	 					}
		 				
		 				if(j > 0)
		 				{
		 					newParams.addRule(RelativeLayout.BELOW, j-1+i);

		 				}
		 				else
		 				{
		 					newParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
	
		 					
		 				}
		 				 box.setLayoutParams(newParams);
		 				//theLayout.addView(box);
		 				
		 				AddViewToScreen(box, spaceWidth*i, spaceHeight*j, false,false);
		 				
		 			}
		 			
		 			
		 		}
		    	 boxes.getViewTreeObserver().removeOnPreDrawListener(this);
		         return true;
		     }
		 });
		 
		 
		 theLayout.addView(boxes);
		
		
		
		
		
	//	AddCommunityPlayer();
		
		Log.d("onCreate", "onCreate is done.");
	}
	


	public void ProcessIntent(Intent i)
	{
		 String type = i.getStringExtra("ResponseType");
		 
		  if(type.equals("OK") || type.equals("ERROR"))
			 {
				 String r = i.getStringExtra("Message");
				 
				 Toast.makeText(getApplicationContext(), r, Toast.LENGTH_LONG).show();
			 }
			 else if(type.equals("NewPlayer"))
			 {
				 String id = i.getStringExtra("Player");
				 String name = i.getStringExtra("Name");
				 
				 if(id.equals(playerID))
				 {
					 return;
				 }
				 
				 Toast.makeText(getApplicationContext(), "New player: " + name + " has joined.", Toast.LENGTH_LONG).show();
				 
				 Player thePlayer = new Player(name, id,getApplicationContext());
				 thePlayer.setImageDrawable((GamePlayActivity.parent.getResources().getDrawable(R.drawable.back)));
				
				 Log.d("Player Joined",thePlayer.playerName);
				
				
				
				 if(!currPlayers.containsKey(id))
				 {
					 Log.d("Player Joined INside",thePlayer.playerName);
					 switch(currPlayers.size())
					 {
						 // Community Deck is at 0,0
						 case 0:

							
							 AddPlayer(name, id, 25, 0); 
							 break;
						 case 1:

							 AddPlayer(name, id, 50, 0);
							 break;
						 case 2:
							 AddPlayer(name, id, 75, 0); 
							 
							 break;
						 case 3:
							 
							 AddPlayer(name, id, 0, 20);
							 
							 break;
						 case 4:
							 
							 AddPlayer(name, id, 25, 20);
							 break;
						 case 5:
							 
							 AddPlayer(name, id, 50, 20);
							 
							 break;
						 case 6:
							 
							 AddPlayer(name, id, 75, 20);
							 break;
							 
						default:
							Toast.makeText(getApplicationContext(), "More than 8 players tried to join!", Toast.LENGTH_LONG).show();
							
							break;
						 
					 }
					 
				 }
				 else
				 {
					 Log.e("OnAddPlayer", "Player already exists");
				 }
				 
				 
				 
			 }
			 else if(type.equals("CardsList"))
			 {
				 
				 String id = i.getStringExtra("Player");
				 String list = i.getStringExtra("Cards");
				 
				 if(id.equals(GamePlayActivity.playerID))
				 {
					 String arrayList[] = list.split(";");

				 
					 playerCards.clear();
					 for(String card : arrayList)
					 {
						 
						 String[] cardSplit = card.split(":");
						 if(cardSplit.length == 2)
						 {
							 Card c = new Card(cardSplit[0],getApplicationContext(),Boolean.valueOf(cardSplit[1]));
							 playerCards.add(c);
								 
								 
								 AddViewToScreen(c, 20, 30,true,true);
						 }
						
					 }
					// GamePlayActivity.parent.setTitle("In Game: " + gameID + "   Cards: " + playerCards.size());

					 
					 
				 }
				 
				 
			 }
			 else if(type.equals("PassCard"))
			 {
				 String id = i.getStringExtra("toPlayer");
				 
				 if(id.equals(GamePlayActivity.playerID))
				 {
					 String card = i.getStringExtra("Card");
					 Card c = new Card(card,getApplicationContext(),Boolean.valueOf(i.getStringExtra("isShown")));
					 playerCards.add(c);
					// theLayout.removeAllViews();
					// AddViewToScreen(c, 40, 30,true,false);
					 
					 //GamePlayActivity.parent.setTitle("In Game: " + gameID + "   Cards: " + playerCards.size());
					 AddViewToScreen(c, 20, 30,true,true);
					 
					 
					 
				 }
				 
			 }

	}
	

	
	/**
	 * create a new player and add it to the game
	 */
	public void AddPlayer(String name, String id, int horizPos, int vertPos)
	{
		Log.d("ADDPLAYER", "Adding Player to: " + horizPos + "," + vertPos);
		Player thePlayer = new Player(name, id, this.getBaseContext());
		thePlayer.setImageDrawable((this.getResources().getDrawable(R.drawable.back)));
		AddPlayer(thePlayer, horizPos, vertPos);
	}
	
	/**
	 * adds the player and updates all the other players location
	 */
	public void AddPlayer(Player newPlayer, int horizPos, int vertPos)
	{
		
		currPlayers.put(newPlayer.playerId,newPlayer);
		AddViewToScreen(newPlayer, horizPos, vertPos, false,true);

		  LayoutParams newParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		  Random rand = new Random();
		  newPlayer.setId(rand.nextInt());
		  newParams.addRule(RelativeLayout.BELOW, newPlayer.getId());
		  newParams.addRule(RelativeLayout.ALIGN_LEFT, newPlayer.getId());
		  theLayout.addView(newPlayer.displayName, newParams);
		
	}
	
	/**
	 * Adds the community player to the screen
	 */
	public void AddCommunityPlayer()
	{
		theCommunity = new CommunityPlayer(this);
		theCommunity.setImageDrawable((this.getResources().getDrawable(R.drawable.back)));
		theCommunity.playerId = "DECK";
		theCommunity.playerName = "Community Deck";

		AddViewToScreen(theCommunity, 0, 0, false,true);


		  LayoutParams newParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		  Random rand = new Random();
		  theCommunity.setId(rand.nextInt());
		  newParams.addRule(RelativeLayout.BELOW, theCommunity.getId());
		  newParams.addRule(RelativeLayout.ALIGN_LEFT, theCommunity.getId());
		  theLayout.addView(theCommunity.displayName, newParams);
		
	}
	/**
	 * changes the screenHeight, screenWidth coordinates
	 */
	void UpdateScreenSize()
	{
		Display currDisplay = getWindowManager().getDefaultDisplay();
		Point outSize = new Point();
		currDisplay.getSize(outSize);
		screenWidth = outSize.x;
		screenHeight = outSize.y;
		
		

	}

	/**
	 * clamps the value between min and max and returns that value
	 */
	public static int clamp(int toCheck, int min, int max)
	{
		if(toCheck >= min && toCheck <= max)
			return toCheck;
		else if(toCheck < min)
			return min;
		else
			return max;	
	}

	/**
	 * Updates and uses the current width and height
	 */
	void UpdateImageLocation(Card theCard, int horizPos, int vertPos)
	{
		UpdateImageLocation(theCard, horizPos, vertPos, theCard.getWidth(), theCard.getHeight());
	}

	/**
	 * Updates and uses the base width and height
	 */
	void UpdatePlayerViewLocation(Player name, int horizPos, int vertPos)
	{
		name.setLayoutParams(getNewLayout(horizPos, vertPos));
	}
	
	/**
	 * Update and resize the width and height
	 */
	void UpdateImageLocation(Card theCard, int horizPos, int vertPos, int width, int  height)
	{
		LayoutParams lp = getNewLayout(horizPos, vertPos, width, height);
		theCard.setLayoutParams(lp);
	}
	
	/**
	 * returns a layout that does not update the width and height
	 */
	LayoutParams getNewLayout(int horizPos, int vertPos)
	{
		LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		vertPos = clamp(vertPos, 0, 100);
		horizPos = clamp(horizPos, 0, 100);
		lp.leftMargin = screenWidth*horizPos/100;
		lp.topMargin = screenHeight*vertPos/100;
		return lp;
		
	

	}
	
	/**
	 * Returns a layout that updates the width and height
	 */
	LayoutParams getNewLayout(int horizPos, int vertPos, int width, int height)
	{
		LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		lp.width = width;
		lp.height = height;
		vertPos = clamp(vertPos, 0, 100);
		horizPos = clamp(horizPos, 0, 100);
		lp.leftMargin = (screenWidth - width)*horizPos/100;
		lp.topMargin = (screenHeight - height)*vertPos/100;
		return lp;
	}

	/**
	 * Initialize a new card and add the card to the screen
	 */
	void AddCardToScreen(Card.CardNumber num, Card.CardSuite suite, int horizPos, int vertPos)
	{
		Card newCard = new Card(num, suite, this, false);
		AddViewToScreen(newCard, horizPos, vertPos, true,true);
	}
	
	/**
	 * Add a new card with the id given at the prescribed coordinates
	 */
	void AddViewToScreen(View viewId, int horizPos, int vertPos, boolean setListeners, boolean setParams)
	{		
		
		viewId.setVisibility(View.VISIBLE);
		viewId.setOnDragListener(new CardDragListener());
		if(setListeners)
		{
			viewId.setOnTouchListener(new CardTouchListener());
		}
		
		if(setParams)
		{
			LayoutParams newLp = getNewLayout(horizPos, vertPos);
			viewId.setLayoutParams(newLp);
			theLayout.addView(viewId, newLp);
		}
		else
		{
			theLayout.addView(viewId);
		}
		
		
	
		/*	for(int i=0; i<((ViewGroup)theLayout).getChildCount(); ++i) 
			{
			    View nextChild = ((ViewGroup)theLayout).getChildAt(i);
			    
			    if(nextChild.equals(viewId));
			    {
			    	theLayout.removeView(viewId);
			    	break;
			    }
			}*/
			
			
		
		
		

	}
	
	void UpdateCard(Card cardInfo, int xPos, int yPos)
	{
		LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		lp.leftMargin = xPos;
		lp.topMargin = yPos;
		
	}

	private final class CardTouchListener implements OnTouchListener 
	{
	    public boolean onTouch(View view, MotionEvent motionEvent) 
	    {
	      int action = motionEvent.getAction();
	      // we have clicked this one
	      if (action == MotionEvent.ACTION_DOWN) 
	      {
	    	Card theCard = (Card)view;
	    	if(theCard != null)
	    	{
	    		//Toast.makeText(getBaseContext(), theCard.toString(), Toast.LENGTH_SHORT).show();
	    	}
	        return true;
	      }
	      //If we get in here we havent started moving and just tapped to change the display of the card
	      else if(action == MotionEvent.ACTION_UP)
	      {
	    	if(view instanceof Card)
	    	{
		    	Card theCard = (Card) view;
		    	if(theCard != null)
		    	{
		   			theCard.Swap(); 		
		    	}
	    	}
	        return true;
	      }
	      //if we moved from where we clicked we shall start the drag
	      else if(action == MotionEvent.ACTION_MOVE)
	      {
		        ClipData data = ClipData.newPlainText("", "");
		        DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
		        if(view instanceof Card)
		        {
			        Card theCard = (Card) view;
			        if(theCard != null)
			        {
			        	theCard.actuallyDragged = true;
			        }
			        view.startDrag(data, shadowBuilder, view, 0);
		        }
	    	  return true;
	      }
	      else
	    	  return false;
	    }
	}
	
	class CardDragListener implements OnDragListener
	{
		public boolean onDrag(View v, final DragEvent event) {
			int action = event.getAction();
			if(event.getLocalState() instanceof Card)
			{
				final Card theCard = (Card)event.getLocalState();
				if(theCard == null)
					return false;
				else
				{
			      switch (action) {
			      case DragEvent.ACTION_DRAG_STARTED:
			        break;
			      case DragEvent.ACTION_DRAG_ENTERED:
			        break;
			      case DragEvent.ACTION_DRAG_EXITED:
			        break;
			      case DragEvent.ACTION_DROP:
			    	  if(v instanceof Player)
			    	  {
				    	  Player destination = (Player) v;
				    	  if(destination != null)
				    	  {
				    		  destination.AddCard(theCard);
				    		  //theCard.setVisibility(View.INVISIBLE);
				    		  theLayout.removeView(theCard);
				    		  playerCards.remove(theCard);
				    		  
				    		  GamePlayActivity.parent.setTitle("In Game: " + gameID + "   Cards: " + playerCards.size());
				    	  
				    	  }
			    	  }
			    	  else if(v instanceof CommunityPlayer)
			    	  {
				    	  CommunityPlayer cDestination = (CommunityPlayer)v;
				    	  if(cDestination != null)
				    	  {
				    		  cDestination.AddCard(theCard);
				    		 // cDestination.setVisibility(View.INVISIBLE);
				    		  theLayout.removeView(theCard);
				    		  playerCards.remove(theCard);
				    		  
				    		  GamePlayActivity.parent.setTitle("In Game: " + gameID + "   Cards: " + playerCards.size());
				    	  }
			    	  }
			    	  else
			    	  {

			    		 
						theLayout.removeView(theCard);
						AddViewToScreen(theCard, Math.round(v.getX()*100/screenWidth), Math.round(v.getY()*100/screenHeight),true,true);
			    		  
			    		  
			    	  }
			        break;
			      case DragEvent.ACTION_DRAG_ENDED:
			      default:
			        break;
			        
			      	}
				}
			}
		      return true;	}
	}	
}
